package de.gameduell.framework.gui.scroll {
	import fl.transitions.easing.Regular;

	import de.gameduell.framework.debug.Debug;
	import de.gameduell.framework.gui.animation.GDTween;
	import de.gameduell.framework.gui.button.Button;
	import de.gameduell.framework.gui.button.ButtonEvent;

	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.utils.Timer;

	/**
	 * @author fsri
	 */
	public class SimpleVScroller {
		private var _btUp:Button;
		private var _btDown:Button;
		private var _content:DisplayObject;
		private var _tween:GDTween;
		private var _step:uint;
		private var _duration:Number;
		private var _direction:int = 1;
		private var _maskDim:Rectangle;
		private var _scrollTimer:Timer;
		private var _steplessTimer:Timer;
		private var _isStepless:Boolean;
		private var _stepIndex:int = 0;
		private var _minStepIndex:int = -20;

		public function SimpleVScroller(btUp:Button, btDown:Button, content:DisplayObject = null, stepLess:Boolean = false, step:uint = 10, duration:Number = 1, rect:Rectangle = null):void {
			init(btUp, btDown, content, stepLess, step, duration, rect);
		}

		//public
		public function triggerScroll(direction:int):void {
			if(_scrollTimer != null) {
				return;
			}
			_direction = direction / Math.abs(direction);
			_scrollTimer = new Timer(_duration, Math.abs(direction));
			_scrollTimer.addEventListener(TimerEvent.TIMER, onTimer);
			_scrollTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onScrollTimerComplete);
			_scrollTimer.start();
		}
		
		public function resetStepIndex():void {
			_stepIndex = 0;
		}

		//private
		private function init(btUp:Button, btDown:Button, content:DisplayObject, stepLess:Boolean, step:uint, duration:Number, rect:Rectangle):void {
			_btUp = btUp;
			_btDown = btDown;
			_content = content;
			_step = step;
			_duration = duration;
			_isStepless = stepLess;
			if(stepLess) {
				_steplessTimer = new Timer(_duration);
				_btUp.addEventListener(ButtonEvent.DOWN, onClickButtonNoSteps);
				_btDown.addEventListener(ButtonEvent.DOWN, onClickButtonNoSteps);
				_btUp.addEventListener(ButtonEvent.UP, onClickButtonNoSteps);
				_btDown.addEventListener(ButtonEvent.UP, onClickButtonNoSteps);
			} else {
				_btUp.addEventListener(ButtonEvent.CLICK, onClickButtonSteps);
				_btDown.addEventListener(ButtonEvent.CLICK, onClickButtonSteps);
			}
			_maskDim = rect;
			if(_content != null) {
				_minStepIndex = Math.round(_content.height / _step);
				if(rect != null && _content.parent != null) {
					drawMask();
				}
			}
		}

		private function drawMask():void {
			var msk:Sprite = new Sprite();
			msk.graphics.lineStyle(1, 0xff0000);
			msk.graphics.beginFill(0xff0000);
			msk.graphics.drawRect(0, 0, _maskDim.width, _maskDim.height);
			_content.parent.addChild(msk);
			msk.x = _content.x;
			msk.y = _content.y;
			_content.mask = msk;
		}

		//getter/setter
		public function set content(value:DisplayObject):void {
			_content = value;
			_minStepIndex = -Math.round(_content.height / _step);
			if(_maskDim != null) {
				drawMask();
				_minStepIndex += Math.round(_maskDim.height / _step);
			}
			_content.y += _stepIndex * _step;
		}

		//handler
		/**
		 * please check if multiple clicks will create multiple tweens
		 * which might cause problems
		 * 
		 * check release outside wich might cause endless scrolling
		 */
		private function onClickButtonSteps(e:ButtonEvent):void {
			if(_content == null || (_tween != null && _tween.isPlaying)) {
				return;
			}
			var dest:Number;
			switch(e.button) {
				case _btUp:
					dest = _content.y + _step;
					break;
				case _btDown:
					dest = _content.y - _step;
					break;
			}
			_tween = new GDTween(_content, "y", Regular.easeIn, _content.y, dest, _duration, true);
			_tween.start();
		}

		/**
		 * why create a tween which never will be used?
		 */
		private function onClickButtonNoSteps(e:ButtonEvent):void {
			switch(e.button) {
				case _btUp:
					_direction = 1;
					break;
				case _btDown:
					_direction = -1;
					break;
			}
			switch(e.type) {
				case ButtonEvent.DOWN:
					_steplessTimer.addEventListener(TimerEvent.TIMER, onTimer);
					_steplessTimer.start();
					break;
				case ButtonEvent.UP:
					_steplessTimer.removeEventListener(TimerEvent.TIMER, onTimer);
					_steplessTimer.stop();
					break;
			}
		}

		private function onTimer(e:Event = null):void {
			if(_tween != null && _tween.isPlaying) {
				_tween.stop();
			}
			if(getScrollPermission()) {
				_content.y += _direction * _step;
				_stepIndex += _direction;
			}
		}
		
		private function onScrollTimerComplete(e:Event):void {
			_scrollTimer.removeEventListener(TimerEvent.TIMER, onTimer);
			_scrollTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, onScrollTimerComplete);
			_scrollTimer = null;
		}

		private function getScrollPermission():Boolean {
			return (_stepIndex < 0 && _direction == 1) || (_stepIndex > _minStepIndex && _direction == -1);
		}
	}
}
